#ifndef IPC_DATA_H
#define IPC_DATA_H

#include <cstdint>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <limits>

// 代码主要来自Android

namespace ipc
{
	// (非框架设计者不用理会这个)
	typedef int32_t status_t;
	
	class Parcel;

	// (非框架设计者不用理会这个)
	class Parcelable {
	public:
		virtual ~Parcelable() = default;

		Parcelable() = default;
		Parcelable(const Parcelable&) = default;

		// Write |this| parcelable to the given |parcel|.  Keep in mind that
		// implementations of writeToParcel must be manually kept in sync
		// with readFromParcel and the Java equivalent versions of these methods.
		//
		// Returns android::OK on success and an appropriate error otherwise.
		virtual status_t writeToParcel(Parcel* parcel) const = 0;

		// Read data from the given |parcel| into |this|.  After readFromParcel
		// completes, |this| should have equivalent state to the object that
		// wrote itself to the parcel.
		//
		// Returns android::OK on success and an appropriate error otherwise.
		virtual status_t readFromParcel(const Parcel* parcel) = 0;
	}; // class Parcelable
	
	
	class Variant
	{
		friend class Bundle;
	public:	// 类型		
		enum
		{
			TYPE_INT8,
			TYPE_INT16,
			TYPE_INT32,
			TYPE_INT64,
			TYPE_FLOAT,
			TYPE_DOUBLE,
			TYPE_STRING,

			TYPE_INT8_VECTOR,
			TYPE_INT16_VECTOR,
			TYPE_INT32_VECTOR,
			TYPE_INT64_VECTOR,
			TYPE_FLOAT_VECTOR,
			TYPE_DOUBLE_VECTOR,
			TYPE_STRING_VECTOR,

			TYPE_MAX,
		};
		
	private:	// 数据
		union Union
		{
			int8_t mInt8;
			int16_t mInt16;
			int32_t mInt32;
			int64_t mInt64;
			float mFloat;
			double mDouble;
			std::string mString;

			std::vector<int8_t> mInt8Vector;
			std::vector<int16_t> mInt16Vector;
			std::vector<int32_t> mInt32Vector;
			std::vector<int64_t> mInt64Vector;
			std::vector<float> mFloatVector;
			std::vector<double> mDoubleVector;
			std::vector<std::string> mStringVector;
					
			Union() : mInt32{0} {}
			~Union() {}
		};

	public:
		Variant() = default;
		~Variant();
		
		Variant(const Variant& rhs);
		Variant(Variant&& rhs);
		
		Variant& operator=(const Variant& rhs);
		Variant& operator=(Variant&& rhs);
		
		friend bool operator==(const Variant& lhs, const Variant& rhs);
		friend bool operator!=(const Variant& lhs, const Variant& rhs);
		
		int getType() const { return mType; };

	public: // 设置
		void setInt8(int8_t value);
		void setInt16(int16_t value);
		void setInt32(int32_t value);
		void setInt64(int64_t value);
		void setFloat(float value);
		void setDouble(double value);
		void setString(const std::string& value);

		void setInt8Vector(const std::vector<int8_t>& value);
		void setInt16Vector(const std::vector<int16_t>& value);
		void setInt32Vector(const std::vector<int32_t>& value);
		void setInt64Vector(const std::vector<int64_t>& value);
		void setFloatVector(const std::vector<float>& value);
		void setDoubleVector(const std::vector<double>& value);
		void setStringVector(const std::vector<std::string>& value);

		void setInt8Vector(std::vector<int8_t>&& value);
		void setInt16Vector(std::vector<int16_t>&& value);
		void setInt32Vector(std::vector<int32_t>&& value);
		void setInt64Vector(std::vector<int64_t>&& value);
		void setFloatVector(std::vector<float>&& value);
		void setDoubleVector(std::vector<double>&& value);
		void setStringVector(std::vector<std::string>&& value);

	public: // 获取
		int8_t getInt8(int8_t defaultValue = 0) const;
		int16_t getInt16(int8_t defaultValue = 0) const;
		int32_t getInt32(int8_t defaultValue = 0) const;
		int64_t getInt64(int8_t defaultValue = 0) const;
		float getFloat(int8_t defaultValue = 0) const;
		double getDouble(int8_t defaultValue = 0) const;
		std::string getString() const;
		std::string getString(const std::string& defaultValue) const;

		std::vector<int8_t> getInt8Vector() const;
		std::vector<int16_t> getInt16Vector() const;
		std::vector<int32_t> getInt32Vector() const;
		std::vector<int64_t> getInt64Vector() const;
		std::vector<float> getFloatVector() const;
		std::vector<double> getDoubleVector() const;
		std::vector<std::string> getStringVector() const;

		const std::vector<int8_t>& getInt8VectorRef() const;
		const std::vector<int16_t>& getInt16VectorRef() const;
		const std::vector<int32_t>& getInt32VectorRef() const;
		const std::vector<int64_t>& getInt64VectorRef() const;
		const std::vector<float>& getFloatVectorRef() const;
		const std::vector<double>& getDoubleVectorRef() const;
		const std::vector<std::string>& getStringVectorRef() const;
		
	private:
		int		mType{ TYPE_INT8 };
		Union	mData;
		
	private: // 清理
		static void clearNone(Variant* v);	
		static void clearString(Variant* v);

		static void clearInt8Vector(Variant* v);
		static void clearInt16Vector(Variant* v);
		static void clearInt32Vector(Variant* v);
		static void clearInt64Vector(Variant* v);
		static void clearFloatVector(Variant* v);
		static void clearDoubleVector(Variant* v);
		static void clearStringVector(Variant* v);

	private: // 复制
		static void copyInt64(Variant* lhs, const Variant& rhs);
		static void copyString(Variant* lhs, const Variant& rhs);
		
		static void copyInt8Vector(Variant* lhs, const Variant& rhs);
		static void copyInt16Vector(Variant* lhs, const Variant& rhs);
		static void copyInt32Vector(Variant* lhs, const Variant& rhs);
		static void copyInt64Vector(Variant* lhs, const Variant& rhs);
		static void copyFloatVector(Variant* lhs, const Variant& rhs);
		static void copyDoubleVector(Variant* lhs, const Variant& rhs);
		static void copyStringVector(Variant* lhs, const Variant& rhs);
		
	private: // 移动
		static void moveString(Variant* lhs, const Variant& rhs);
		
		static void moveInt8Vector(Variant* lhs, const Variant& rhs);
		static void moveInt16Vector(Variant* lhs, const Variant& rhs);
		static void moveInt32Vector(Variant* lhs, const Variant& rhs);
		static void moveInt64Vector(Variant* lhs, const Variant& rhs);
		static void moveFloatVector(Variant* lhs, const Variant& rhs);
		static void moveDoubleVector(Variant* lhs, const Variant& rhs);
		static void moveStringVector(Variant* lhs, const Variant& rhs);
				
	private: // 比较
		static bool equalInt8(const Union& lhs, const Union& rhs);
		static bool equalInt16(const Union& lhs, const Union& rhs);
		static bool equalInt32(const Union& lhs, const Union& rhs);
		static bool equalInt64(const Union& lhs, const Union& rhs);
		static bool equalFloat(const Union& lhs, const Union& rhs);
		static bool equalDouble(const Union& lhs, const Union& rhs);
		static bool equalString(const Union& lhs, const Union& rhs);
		
		static bool equalInt8Vector(const Union& lhs, const Union& rhs);
		static bool equalInt16Vector(const Union& lhs, const Union& rhs);
		static bool equalInt32Vector(const Union& lhs, const Union& rhs);
		static bool equalInt64Vector(const Union& lhs, const Union& rhs);
		static bool equalFloatVector(const Union& lhs, const Union& rhs);
		static bool equalDoubleVector(const Union& lhs, const Union& rhs);
		static bool equalStringVector(const Union& lhs, const Union& rhs);

	private: // 写入
		static status_t writeInt8(Parcel* parcel, const Variant& v);
		static status_t writeInt16(Parcel* parcel, const Variant& v);
		static status_t writeInt32(Parcel* parcel, const Variant& v);
		static status_t writeInt64(Parcel* parcel, const Variant& v);
		static status_t writeFloat(Parcel* parcel, const Variant& v);
		static status_t writeDouble(Parcel* parcel, const Variant& v);
		static status_t writeString(Parcel* parcel, const Variant& v);
		
		static status_t writeInt8Vector(Parcel* parcel, const Variant& v);
		static status_t writeInt16Vector(Parcel* parcel, const Variant& v);
		static status_t writeInt32Vector(Parcel* parcel, const Variant& v);
		static status_t writeInt64Vector(Parcel* parcel, const Variant& v);
		static status_t writeFloatVector(Parcel* parcel, const Variant& v);
		static status_t writeDoubleVector(Parcel* parcel, const Variant& v);
		static status_t writeStringVector(Parcel* parcel, const Variant& v);
	
	private: // 读取
		static status_t readInt8(Variant& v, const Parcel* parcel);
		static status_t readInt16(Variant& v, const Parcel* parcel);
		static status_t readInt32(Variant& v, const Parcel* parcel);
		static status_t readInt64(Variant& v, const Parcel* parcel);
		static status_t readFloat(Variant& v, const Parcel* parcel);
		static status_t readDouble(Variant& v, const Parcel* parcel);
		static status_t readString(Variant& v, const Parcel* parcel);
		
		static status_t readInt8Vector(Variant& v, const Parcel* parcel);
		static status_t readInt16Vector(Variant& v, const Parcel* parcel);
		static status_t readInt32Vector(Variant& v, const Parcel* parcel);
		static status_t readInt64Vector(Variant& v, const Parcel* parcel);
		static status_t readFloatVector(Variant& v, const Parcel* parcel);
		static status_t readDoubleVector(Variant& v, const Parcel* parcel);
		static status_t readStringVector(Variant& v, const Parcel* parcel);

	private:
		typedef void (*ClearFunc)(Variant*);
		typedef void (*CopyFunc)(Variant*, const Variant&);
		typedef void (*MoveFunc)(Variant*, const Variant&);
		typedef bool (*EqualFunc)(const Union&, const Union&);
		typedef status_t (*WriteFunc)(Parcel*, const Variant&);
		typedef status_t (*ReadFunc)(Variant&, const Parcel*);
		
		static const ClearFunc CLEAR_FUNCS[TYPE_MAX];
		static const CopyFunc COPY_FUNCS[TYPE_MAX];
		static const MoveFunc MOVE_FUNCS[TYPE_MAX];
		static const EqualFunc EQUAL_FUNCS[TYPE_MAX];
		static const WriteFunc WRITE_FUNCS[TYPE_MAX];
		static const ReadFunc READ_FUNCS[TYPE_MAX];
	};
	

	// IPC通讯要传输的key-value容器(非框架设计者主要是使用这个类)
	class Bundle : public Parcelable {
	public:
		// 默认
		virtual ~Bundle() = default;
		Bundle() = default;
		Bundle(const Bundle& bundle) = default;
		Bundle& operator=(const Bundle& bundle) = default;

		// 右值(MOVE语义)
		Bundle(Bundle&& bundle);
		Bundle& operator=(Bundle&& bundle);

		status_t writeToParcel(Parcel* parcel) const override;
		status_t readFromParcel(const Parcel* parcel) override;

		bool empty() const;
		size_t size() const;
		size_t erase(const std::string& key);

		// 设置(支持链式调用) -------------------------------------------------------------------------------------
		/*
		 * Setters for PersistableBundle. Adds a a key-value pair instantiated with
		 * |key| and |value| into the member map appropriate for the type of |value|.
		 * If there is already an existing value for |key|, |value| will replace it.
		 */
		Bundle& setInt8(const std::string& key, const int8_t value);
		Bundle& setInt16(const std::string& key, const int16_t value);
		Bundle& setInt32(const std::string& key, const int32_t value);
		Bundle& setInt64(const std::string& key, const int64_t value);
		Bundle& setFloat(const std::string& key, const float value);
		Bundle& setDouble(const std::string& key, const double value);
		Bundle& setString(const std::string& key, const std::string& value);

		Bundle& setInt8Vector(const std::string& key, const std::vector<int8_t>& value);
		Bundle& setInt16Vector(const std::string& key, const std::vector<int16_t>& value);
		Bundle& setInt32Vector(const std::string& key, const std::vector<int32_t>& value);
		Bundle& setInt64Vector(const std::string& key, const std::vector<int64_t>& value);
		Bundle& setFloatVector(const std::string& key, const std::vector<float>& value);
		Bundle& setDoubleVector(const std::string& key, const std::vector<double>& value);
		Bundle& setStringVector(const std::string& key, const std::vector<std::string>& value);

		// 设置(右值版本,防止大规模变量拷贝) ---------------------------------------------------------------------------------------;

		Bundle& setInt8Vector(const std::string& key, std::vector<int8_t>&& value);
		Bundle& setInt16Vector(const std::string& key, std::vector<int16_t>&& value);
		Bundle& setInt32Vector(const std::string& key, std::vector<int32_t>&& value);
		Bundle& setInt64Vector(const std::string& key, std::vector<int64_t>&& value);
		Bundle& setFloatVector(const std::string& key, std::vector<float>&& value);
		Bundle& setDoubleVector(const std::string& key, std::vector<double>&& value);
		Bundle& setStringVector(const std::string& key, std::vector<std::string>&& value);

		// 获取 -------------------------------------------------------------------------------------------------

		/*
		 * Getters for PersistableBundle. If |key| exists, these methods write the
		 * value associated with |key| into |out|, and return true. Otherwise, these
		 * methods return false.
		 */
		int8_t getInt8(const std::string& key, const int8_t defaultValue = 0) const;
		int16_t getInt16(const std::string& key, const int16_t defaultValue = 0) const;
		int32_t getInt32(const std::string& key, const int32_t defaultValue = 0) const;
		int64_t getInt64(const std::string& key, const int64_t defaultValue = 0) const;
		float getFloat(const std::string& key, const float defaultValue = 0) const;
		double getDouble(const std::string& key, const double defaultValue = 0) const;
		std::string getString(const std::string& key) const;
		std::string getString(const std::string& key, const std::string& defaultValue) const;

		std::vector<int8_t> getInt8Vector(const std::string& key) const;
		std::vector<int16_t> getInt16Vector(const std::string& key) const;
		std::vector<int32_t> getInt32Vector(const std::string& key) const;
		std::vector<int64_t> getInt64Vector(const std::string& key) const;
		std::vector<float> getFloatVector(const std::string& key) const;
		std::vector<double> getDoubleVector(const std::string& key) const;
		std::vector<std::string> getStringVector(const std::string& key) const;
				
		const std::vector<int8_t>& getInt8VectorRef(const std::string& key) const;
		const std::vector<int16_t>& getInt16VectorRef(const std::string& key) const;
		const std::vector<int32_t>& getInt32VectorRef(const std::string& key) const;
		const std::vector<int64_t>& getInt64VectorRef(const std::string& key) const;
		const std::vector<float>& getFloatVectorRef(const std::string& key) const;
		const std::vector<double>& getDoubleVectorRef(const std::string& key) const;
		const std::vector<std::string>& getStringVectorRef(const std::string& key) const;


		// 键 --------------------------------------------------------------------------------------------------

		/* Getters for all keys for each value type */
		std::set<std::string> getKeySet() const;
		int getType(const std::string& key) const;

		friend bool operator==(const Bundle& lhs, const Bundle& rhs);
		friend bool operator!=(const Bundle& lhs, const Bundle& rhs);

	private:
		status_t writeToParcelInner(Parcel* parcel) const;
		status_t readFromParcelInner(const Parcel* parcel, size_t length);
		
	private:
		std::map<std::string, Variant> mMap;
		
	public:
		static const Bundle& getEmpty();
	};
	
	// Bundle辅助类,用于设置/或者id, 客户端名称, 和额外的单个附加值
	class BundleHelper
	{
	public:
		// 设置/获取id
		std::string getId(const Bundle& data);
		void setId(Bundle& data, const std::string& id);
		
		// 获取客户端名称
		std::string getClientName(const Bundle& data);
		
		// 设置值
	public:	
		void setInt8(Bundle& data, const int8_t value);
		void setInt16(Bundle& data, const int16_t value);
		void setInt32(Bundle& data, const int32_t value);
		void setInt64(Bundle& data, const int64_t value);
		void setFloat(Bundle& data, const float value);
		void setDouble(Bundle& data, const double value);
		void setString(Bundle& data, const std::string& value);

		void setInt8Vector(Bundle& data, const std::vector<int8_t>& value);
		void setInt16Vector(Bundle& data, const std::vector<int16_t>& value);
		void setInt32Vector(Bundle& data, const std::vector<int32_t>& value);
		void setInt64Vector(Bundle& data, const std::vector<int64_t>& value);
		void setFloatVector(Bundle& data, const std::vector<float>& value);
		void setDoubleVector(Bundle& data, const std::vector<double>& value);
		void setStringVector(Bundle& data, const std::vector<std::string>& value);

		// 设置(右值版本,防止大规模变量拷贝) ---------------------------------------------------------------------------------------;

		void setInt8Vector(Bundle& data, std::vector<int8_t>&& value) const;
		void setInt16Vector(Bundle& data, std::vector<int16_t>&& value) const;
		void setInt32Vector(Bundle& data, std::vector<int32_t>&& value) const;
		void setInt64Vector(Bundle& data, std::vector<int64_t>&& value) const;
		void setFloatVector(Bundle& data, std::vector<float>&& value) const;
		void setDoubleVector(Bundle& data, std::vector<double>&& value) const;
		void setStringVector(Bundle& data, std::vector<std::string>&& value) const;

		// 获取 -------------------------------------------------------------------------------------------------

		int8_t getInt8(const Bundle& data, const int8_t defaultValue = 0) const;
		int16_t getInt16(const Bundle& data, const int16_t defaultValue = 0) const;
		int32_t getInt32(const Bundle& data, const int32_t defaultValue = 0) const;
		int64_t getInt64(const Bundle& data, const int64_t defaultValue = 0) const;
		float getFloat(const Bundle& data, const float defaultValue = 0) const;
		double getDouble(const Bundle& data, const double defaultValue = 0) const;
		std::string getString(const Bundle& data, const std::string& defaultValue = std::string()) const;

		std::vector<int8_t> getInt8Vector(const Bundle& data) const;
		std::vector<int16_t> getInt16Vector(const Bundle& data) const;
		std::vector<int32_t> getInt32Vector(const Bundle& data) const;
		std::vector<int64_t> getInt64Vector(const Bundle& data) const;
		std::vector<float> getFloatVector(const Bundle& data) const;
		std::vector<double> getDoubleVector(const Bundle& data) const;
		std::vector<std::string> getStringVector(const Bundle& data) const;
				
		const std::vector<int8_t>& getInt8VectorRef(const Bundle& data) const;
		const std::vector<int16_t>& getInt16VectorRef(const Bundle& data) const;
		const std::vector<int32_t>& getInt32VectorRef(const Bundle& data) const;
		const std::vector<int64_t>& getInt64VectorRef(const Bundle& data) const;
		const std::vector<float>& getFloatVectorRef(const Bundle& data) const;
		const std::vector<double>& getDoubleVectorRef(const Bundle& data) const;
		const std::vector<std::string>& getStringVectorRef(const Bundle& data) const;
	};
	
	
	// 工具类
	class IpcKit
	{
	public:
		static void init();
		static void join();
		
		// 一些常用的key
	public:
		// 每个数据都应该包含一个id
		static const std::string& getKeyId();
		
		// 这个用于告诉服务器是哪个客户端发送过来的消息
		static const std::string& getKeyClient();
		
		// 告诉客户端哪个监听器应该响应
		static const std::string& getKeyObserver();
		
		// 通常数据只附加一个参数
		static const std::string& getKeyValue();
		
		// 空字符串
		static const std::string& getEmptyStr();
		
	public:
		// 设置/获取id
		static void setId(Bundle& data, const std::string& id);
		static std::string getId(const Bundle& data);
		
		// 获取客户端名称
		static std::string getClientName(const Bundle& data);
		
	public:
		// 获取服务名
		static std::string getServiceNameFromId(const std::string& id);
		
		// 获取服务名
		static std::string getServiceNameFromId(std::string&& id);
	};
	
	// (非框架设计者不用理会这个)
	enum {
		OK = 0, // Everything's swell.
		NO_ERROR = 0, // No errors.

		UNKNOWN_ERROR = (-2147483647 - 1), // INT32_MIN value

		NO_MEMORY = -ENOMEM,
		INVALID_OPERATION = -ENOSYS,
		BAD_VALUE = -EINVAL,
		BAD_TYPE = (UNKNOWN_ERROR + 1),
		NAME_NOT_FOUND = -ENOENT,
		PERMISSION_DENIED = -EPERM,
		NO_INIT = -ENODEV,
		ALREADY_EXISTS = -EEXIST,
		DEAD_OBJECT = -EPIPE,
		FAILED_TRANSACTION = (UNKNOWN_ERROR + 2),

		BAD_INDEX = -EOVERFLOW,
		NOT_ENOUGH_DATA = -ENODATA,
		WOULD_BLOCK = -EWOULDBLOCK,
		TIMED_OUT = -ETIMEDOUT,
		UNKNOWN_TRANSACTION = -EBADMSG,

		FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7),
		UNEXPECTED_NULL = (UNKNOWN_ERROR + 8),
	};
	
	// 序列化/反序列化工具(非框架设计者不用理会这个)
	class Parcel {
	public:
		Parcel();
		Parcel(const void* data, size_t len);
		~Parcel();

		Parcel(const Parcel& o) = delete;
		Parcel& operator=(const Parcel& o) = delete;

	public:
		const uint8_t* data() const;
		size_t dataSize() const;
		size_t dataAvail() const;
		size_t dataPosition() const;
		size_t dataCapacity() const;

		status_t setDataSize(size_t size);
		void setDataPosition(size_t pos) const;
		status_t setDataCapacity(size_t size);

		void freeData();

	public:
		status_t write(const void* data, size_t len);
		void* writeInplace(size_t len);

		status_t writeInt8(const int8_t val);
		status_t writeInt16(const int16_t val);
		status_t writeInt32(const int32_t val);
		status_t writeInt64(const int64_t val);
		status_t writeFloat(const float val);
		status_t writeDouble(const double val);
		status_t writeString(const std::string& str);

		status_t writeInt8Vector(const std::vector<int8_t>& val);
		status_t writeInt16Vector(const std::vector<int16_t>& val);
		status_t writeInt32Vector(const std::vector<int32_t>& val);
		status_t writeInt64Vector(const std::vector<int64_t>& val);
		status_t writeFloatVector(const std::vector<float>& val);
		status_t writeDoubleVector(const std::vector<double>& val);
		status_t writeStringVector(const std::vector<std::string>& val);

	public:
		status_t read(void* outData, size_t len) const;
		const void* readInplace(size_t len) const;

		status_t readInt8(int8_t* pArg) const;
		status_t readInt16(int16_t* pArg) const;
		status_t readInt32(int32_t* pArg) const;
		status_t readInt64(int64_t* pArg) const;
		status_t readFloat(float* pArg) const;
		status_t readDouble(double* pArg) const;
		status_t readString(std::string* pArg) const;

		status_t readInt8Vector(std::vector<int8_t>* val) const;
		status_t readInt16Vector(std::vector<int16_t>* val) const;
		status_t readInt32Vector(std::vector<int32_t>* val) const;
		status_t readInt64Vector(std::vector<int64_t>* val) const;
		status_t readFloatVector(std::vector<float>* val) const;
		status_t readDoubleVector(std::vector<double>* val) const;
		status_t readStringVector(std::vector<std::string>* val) const;

		int32_t readInt32() const;

	private:
		void initState();
		void freeDataNoInit();

		status_t finishWrite(size_t len);
		status_t growData(size_t len);
		status_t continueWrite(size_t desired);

		template <class T>
		status_t writeAligned(T val);

		template <class T>
		status_t readAligned(T* pArg) const;

		template <class T>
		T readAligned() const;

	private:
		status_t mError;
		uint8_t* mData;
		size_t mDataSize;
		size_t mDataCapacity;
		mutable size_t mDataPos;
	}; // class Parcel

}

#endif